package org.gitos.cloud.domain.tcp;

import io.netty.channel.ChannelHandlerContext;

import java.io.Serializable;

import org.gitos.cloud.util.ByteUtil;

import com.alibaba.fastjson.annotation.JSONField;

/**
 * Bucket
 * 一个数据包
 *
 * @author purely
 * @date 2015/12/4
 */
public class Bucket implements Serializable {


    //head length
    public static final int HEAD_LENGTH = 23;

    @JSONField(serialize = false, deserialize=false)
    private ChannelHandlerContext ctx;
    //包内容长度 2byte
    private short length;
    //魔幻数字
    private short magic;
    //crc校验
    private short crc;
    // version field
    private byte version;
    //command 2 bytes
    private short cmd;
    // device ID 6 bytes
    private DeviceId deviceId = new DeviceId();
    //数据报序号 4bytes
    private Sequeue dataSeq = new Sequeue();
    //应答序号 4bytes
    private Sequeue ackSeq = new Sequeue();
    //内容
    private byte[] content = new byte[0];

    public Bucket() {
    }

    public Bucket(ChannelHandlerContext ctx) {
        this.ctx = ctx;
    }

    public ChannelHandlerContext getCtx() {
        return ctx;
    }

    public void setCtx(ChannelHandlerContext ctx) {
        this.ctx = ctx;
    }


    public short getLength() {
        int totalLength = HEAD_LENGTH + content.length;
        length = (short) totalLength;
        return length;
    }

    public void setLength(short length) {
        this.length = length;
    }

    public byte[] getContent() {
        return content;
    }

    public void setContent(byte[] content) {
        this.content = content;
    }

    public short getMagic() {
        return magic;
    }

    public void setMagic(short magic) {
        this.magic = magic;
    }

    public short getCrc() {
        return crc;
    }

    public void setCrc(short crc) {
        this.crc = crc;
    }

    public byte getVersion() {
        return version;
    }

    public void setVersion(byte version) {
        this.version = version;
    }

    public short getCmd() {
        return cmd;
    }

    public void setCmd(short cmd) {
        this.cmd = cmd;
    }

    public DeviceId getDeviceId() {
        return deviceId;
    }

    public void setDeviceId(DeviceId deviceId) {
        this.deviceId = deviceId;
    }

    public Sequeue getDataSeq() {
        return dataSeq;
    }

    public void setDataSeq(Sequeue dataSeq) {
        this.dataSeq = dataSeq;
    }

    public Sequeue getAckSeq() {
        return ackSeq;
    }

    public void setAckSeq(Sequeue ackSeq) {
        this.ackSeq = ackSeq;
    }

    public byte[] toFrame() {
        // copy length;

        byte[] buf = new byte[getLength()];

        int offset = 0;

        byte[] lenArray = ByteUtil.short2Bytes(this.length);
        System.arraycopy(lenArray, 0, buf, offset, lenArray.length);
        offset += lenArray.length;

        // copy magic
        byte[] magicArry = ByteUtil.short2Bytes(this.magic);
        System.arraycopy(magicArry, 0, buf, offset, magicArry.length);
        offset += magicArry.length;

        //copy crc
        byte[] crcArry = ByteUtil.short2Bytes(this.crc);
        System.arraycopy(crcArry, 0, buf, offset, crcArry.length);
        offset += crcArry.length;

        byte[] versionArray = new byte[]{version};
        System.arraycopy(versionArray, 0, buf, offset, versionArray.length);
        offset += versionArray.length;

        byte[] cmdArray = ByteUtil.short2Bytes(this.cmd);
        System.arraycopy(cmdArray, 0, buf, offset, cmdArray.length);
        offset += cmdArray.length;

        byte[] deviceIdArray = deviceId.getValue();
        System.arraycopy(deviceIdArray, 0, buf, offset, deviceIdArray.length);
        offset += deviceIdArray.length;

        byte[] dataSeqArray = dataSeq.getValue();
        System.arraycopy(dataSeqArray, 0, buf, offset, dataSeqArray.length);
        offset += dataSeqArray.length;

        byte[] ackSeqArray = ackSeq.getValue();
        System.arraycopy(ackSeqArray, 0, buf, offset, ackSeqArray.length);
        offset += ackSeqArray.length;

        System.arraycopy(content, 0, buf, offset, content.length);
        return buf;
    }
}
